
#include "glad/glad.h"

#include <iostream>

#include <GL/glut.h>
#include <glm/glm.hpp>
#include <glm/ext.hpp>

void wsl_init() __attribute__((constructor));
void wsl_init()
{
    char *wslDistro = std::getenv("WSL_DISTRO_NAME");
    if (wslDistro && wslDistro[0] != '\0') {
        setenv("DISPLAY", "172.20.10.3:0.0", 1);
        setenv("MESA_GL_VERSION_OVERRIDE", "3.3", 1);
    }
}

// 窗口大小
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;

GLuint shaderProgram;

// 顶点数据
GLfloat vertices[] = {
    -0.5f, -0.5f, 0.0f,
    0.5f, -0.5f, 0.0f,
    0.0f, 0.5f, 0.0f};

// 着色器源代码
const char *vertexShaderSource = R"(
#version 330 core
layout(location = 0) in vec3 position;

out vec3 fragColor;

uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;

void main()
{
    // 设置三角形的顶点颜色
    if (gl_VertexID == 0) {
        fragColor = vec3(1.0, 0.0, 0.0); // 红色
    } else if (gl_VertexID == 1) {
        fragColor = vec3(0.0, 1.0, 0.0); // 绿色
    } else if (gl_VertexID == 2) {
        fragColor = vec3(0.0, 0.0, 1.0); // 蓝色
    }
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
}
)";

const char *fragmentShaderSource = R"(
#version 330 core

in vec3 fragColor;
uniform vec3 color;

void main()
{
    gl_FragColor = vec4(fragColor, 1.0);
}
)";

// 检查编译错误和链接错误
bool checkCompileErrors(GLuint shader, std::string type)
{
    GLint success;
    GLchar infoLog[1024];

    if (type != "PROGRAM") {
        glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
        if (!success) {
            glGetShaderInfoLog(shader, 1024, NULL, infoLog);
            std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n"
                      << infoLog << "\n";
            return false;
        }
    } else {
        glGetProgramiv(shader, GL_LINK_STATUS, &success);
        if (!success) {
            glGetProgramInfoLog(shader, 1024, NULL, infoLog);
            std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n"
                      << infoLog << "\n";
            return false;
        }
    }

    return true;
}

void display(void)
{
    // 清空颜色缓冲
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    // 使用着色器程序
    glUseProgram(shaderProgram);

    // 设置 uniform 变量值
    GLint modelLoc = glGetUniformLocation(shaderProgram, "modelMatrix");
    GLint viewLoc = glGetUniformLocation(shaderProgram, "viewMatrix");
    GLint projectionLoc = glGetUniformLocation(shaderProgram, "projectionMatrix");
    glm::mat4 modelMatrix = glm::mat4(1.0f); // 初始化为单位矩阵
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix)); // 设置模型矩阵值
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix)); // 设置视图矩阵值
    glm::mat4 projection = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f);
    glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection)); // 设置投影矩阵值

    GLint colorLoc = glGetUniformLocation(shaderProgram, "color");
    glUniform3f(colorLoc, 1.0f, 0.5f, 0.2f); // 设置颜色值

    // 绘制三角形
    glDrawArrays(GL_TRIANGLES, 0, 3);

    glutSwapBuffers();
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(400, 400);
    glutCreateWindow("Simple OpenGL Example");

    gladLoadGL();
    glClearColor(0.0, 0.0, 0.0, 0.0);

    glutDisplayFunc(display);

    // 创建顶点缓冲对象（VBO）
    GLuint VBO;
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // 编译顶点着色器
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    if (!checkCompileErrors(vertexShader, "VERTEX")) {
        return -1;
    }

    // 编译片元着色器
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    if (!checkCompileErrors(fragmentShader, "FRAGMENT")) {
        return -1;
    }

    // 创建着色器程序
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    if (!checkCompileErrors(shaderProgram, "PROGRAM")) {
        return -1;
    }

    // 设置顶点属性指针
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void *)0);
    glEnableVertexAttribArray(0);

    glutMainLoop();

    // 清理并退出
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    glDeleteProgram(shaderProgram);

    return 0;
}
